Acquiring Data

Acquiring data from Yahoo Finance of AAPL, NFLX, ROKU, SPOT, DIS equities

library(plotly)
library(ggplot2)
library(quantmod)
library(PerformanceAnalytics)
library(dplyr)

#starting data
dt<-'2018-2-1'
#getting data
aapl_df<-data.frame(getSymbols.yahoo('AAPL', from=dt, auto.assign=F))
nflx_df<-data.frame(getSymbols.yahoo('NFLX', from=dt, auto.assign=F))
roku_df<-data.frame(getSymbols.yahoo('ROKU', from=dt, auto.assign=F))
spot_df<-data.frame(getSymbols.yahoo('SPOT', from=dt, auto.assign=F))
dis_df<-data.frame(getSymbols.yahoo('DIS', from=dt, auto.assign=F))

Data Overview

Looking at SPOT equity data as an example

spot_table<-head(spot_df,10)
spot_table

Data Preparation

Manipulating raw equity data for future analysis


data_prep_func<-function(x, y){
  #sma
  sma10<-SMA(x[6], n=10)
  #ema
  ema20<-EMA(x[6], n=20)
  #BBands
  bbands20 <- data.frame(BBands( Cl(x), n=20, sd=2))
  bbands20 <- bbands20[,c(1,3)]
  #changing colnames
  colnames(sma10)<-c(paste0(y,'.SMA'))
  colnames(ema20)<-c(paste0(y,'.EMA'))
  colnames(bbands20)<-c(paste0(y,'.dn'), paste0(y,'.up'))
  #merge/formatting
  new_df<-x
  new_df<-cbind(new_df, sma10)
  new_df<-cbind(new_df, ema20)
  new_df<-cbind(new_df, bbands20)
  new_df<-cbind(Date=rownames(new_df), new_df)
  rownames(new_df)<-1:nrow(new_df)
  #volume differentiation calc
  for(v in 1:length(new_df[,1])){
    if(new_df[v, 5] >= new_df[v, 2]){
      new_df[v, 'volumetype']='Increasing'
    } else if(abs(new_df[v, 5]-new_df[v,2]) < 0.4){
      new_df[v, 'volumetype']='Doji'
    } else {
      new_df[v, 'volumetype']='Decreasing'
    }
  }
  #return
  return(new_df)
}
#running func
aapl_df<-data_prep_func(aapl_df, 'AAPL')
dis_df<-data_prep_func(dis_df, 'DIS')
nflx_df<-data_prep_func(nflx_df, 'NFLX')
roku_df<-data_prep_func(roku_df, 'ROKU')
spot_df<-data_prep_func(spot_df, 'SPOT')

Data Visualization

Creating a dynamic plot with Plotly lib

data_viz1_func<-function(df, eq_name){
  #starting data
  dt<-'2018-2-1'
  #today's date
  today_date<-Sys.Date()
  #plot
  candle_fig <- plot_ly(x = df[[1]], type="candlestick",
                      open = df[[2]], close = df[[5]],
                      high = df[[3]], low = df[[4]], name=eq_name,
                      width=900, height=800)
  candle_fig <- candle_fig %>% add_lines(x = df[[1]], y = df[[8]],
                                       line = list(color = 'rgb(255, 153, 102)',
                                                   width = 0.8),
                                       name='SMA-10', inherit = F)
  candle_fig <- candle_fig %>% add_lines(x = df[[1]], y = df[[9]],
                                       line = list(color='blue',
                                                   width=0.8),
                                       name='EMA-20', inherit = F)
  candle_fig <- candle_fig %>% add_lines(x = df[[1]], y = df[[10]],
                                       line = list(color='#dad3e0',
                                                   width=0.8,
                                                   opacity=0.6),
                                       name='BBands.dn', inherit = F)
  candle_fig <- candle_fig %>% add_lines(x = df[[1]], y = df[[11]],
                                       line = list(color='#dad3e0',
                                                   width=0.8,
                                                   opacity=0.6),
                                       name='BBAnds.up', inherit = F)
  volume_fig <- aapl_df %>% plot_ly(x= df[[1]], y= df[[6]],
                                  type='bar', name = df[[12]],
                                  color= df[[12]],
                                  colors=c('#ff9999',
                                           '#ffff99',
                                           '#99ffb3')
                                  )
  #layout
  volume_fig <- volume_fig %>% layout(yaxis=list(title='Volume',
                                               titlefont=list(size=15)))
  final_fig <- subplot(candle_fig, volume_fig, heights = c(0.7,0.2), nrows=2,
               shareX = TRUE, titleY = TRUE)
  final_fig <- final_fig %>% layout(
    title=list(text=paste0(eq_name,': ',dt,' - ',as.character(today_date)),
               font=list(size=22), y = 0.97),
    xaxis=list(type='date', tickformat = "%d %B <br>%Y",
               title=FALSE, tickfont=list(size=14)),
    yaxis=list(title="Price", titlefont=list(size=16),
               tickfont=list(size=14)),
    legend=list(orientation = 'h', x = 0.5, y = 0.93,
                xanchor = 'center', font = list(size=12),
                bgcolor = 'transparent')
  
  )
  #show
  final_fig
}

Apple (AAPL) Graph

data_viz1_func(aapl_df, 'AAPL')

Disney (DIS) Graph

data_viz1_func(dis_df, 'DIS')

Netflix (NFLX) Graph

data_viz1_func(nflx_df, 'NFLX')

Roku (ROKU) Graph

data_viz1_func(roku_df, 'ROKU')

Spotify (SPOT) Graph

data_viz1_func(spot_df, 'SPOT')

Portfolio Analysis

Analysis of returns and equally weighted portfolio case study

Performance of selected equities independently

#'AAPL', 'DIS', 'NFLX', 'ROKU', 'SPOT'
aapl_dret<-na.omit(dailyReturn(Ad(getSymbols.yahoo('AAPL',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)), type='arithmetic'))
dis_dret<-na.omit(dailyReturn(Ad(getSymbols.yahoo('DIS',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)), type='arithmetic'))
nflx_dret<-na.omit(dailyReturn(Ad(getSymbols.yahoo('NFLX',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)), type='arithmetic'))
roku_dret<-na.omit(dailyReturn(Ad(getSymbols.yahoo('ROKU',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)), type='arithmetic'))
spot_dret<-na.omit(dailyReturn(Ad(getSymbols.yahoo('SPOT',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)), type='arithmetic'))
#renaming cols
colnames(aapl_dret)<-'AAPL.Ad.Returns'
colnames(dis_dret)<-'DIS.Ad.Returns'
colnames(nflx_dret)<-'NFLX.Ad.Returns'
colnames(roku_dret)<-'ROKU.Ad.Returns'
colnames(spot_dret)<-'SPOT.Ad.Returns'
#merging
dret_data<-cbind(aapl_dret,dis_dret,
                 nflx_dret,roku_dret,spot_dret)


table.AnnualizedReturns(dret_data, scale=252, Rf=0.015/252)
#plotting performance
charts.PerformanceSummary(dret_data, main='Portfolio Performance',
                          Rf=0.015/252, plot.engine='default')

Equally weighted portfolio case study and analysis

#eq weighted portfolio
portret_df<-Return.portfolio(dret_data,
                             weights=c(.20,.20,.20,.20,.20))
NA's detected: filling NA's with zeros
colnames(portret_df)<-'Porfolio.Eqw.Returns'

#performance benchmark
benchmarkPrices<-na.omit(dailyReturn(Ad(getSymbols.yahoo('^GSPC',
                                        from=dt,
                                        periodicity='daily',
                                        auto.assign=F)),
                                     type='arithmetic'))
colnames(benchmarkPrices)<-'Benchmark.SP500.Returns'

#merging portfolio and benchmark together
EqWPort.Benchmark_df<-merge(portret_df, benchmarkPrices)
#performance table 
table.AnnualizedReturns(EqWPort.Benchmark_df, scale=252, Rf=0.015/252)

EqWPort.Benchmark_df<-data.frame(EqWPort.Benchmark_df)
EqWPort.Benchmark_df<-cbind(Date=rownames(EqWPort.Benchmark_df),
                            EqWPort.Benchmark_df)
rownames(EqWPort.Benchmark_df)<-1:nrow(EqWPort.Benchmark_df)

perf_fig<-EqWPort.Benchmark_df %>% plot_ly(x= ~Date,
                                      y=~Porfolio.Eqw.Returns,
                                      type='scatter',
                                      mode='lines',
                                      line = list(color='green',
                                             width=0.8),
                                 name='Portfolio', inherit = F,
                                 width=900, height=600)
The inherit argument has been deprecated.
perf_fig<-perf_fig %>% add_lines(x = ~Date,
                                 y = ~Benchmark.SP500.Returns,
                                 line = list(color='blue',
                                             width=0.8),
                                 name='S&P500', inherit = F)

#starting data
dt<-'2018-2-1'
#today's date
today_date<-Sys.Date()

#layout
perf_fig<- perf_fig %>% layout(
  title=list(text=paste0('Portfolio - S&P500',': ',dt,' - ',as.character(today_date)),
               font=list(size=22), y = 0.97),
  xaxis=list(type='date', tickformat = "%d %B <br>%Y",
               title=FALSE, tickfont=list(size=14)),
  yaxis=list(title="Returns", titlefont=list(size=16),
               tickfont=list(size=14))
  
)

perf_fig

NA
LS0tDQp0aXRsZTogIlF1YW50IEZpbmFuY2UgKFN0cmVhbWluZyBTZXJ2aWNlcyBQb3J0Zm9saW8pIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KLS0tDQoNCiMjIEFjcXVpcmluZyBEYXRhDQpBY3F1aXJpbmcgZGF0YSBmcm9tIFlhaG9vIEZpbmFuY2Ugb2YgQUFQTCwgTkZMWCwgUk9LVSwgU1BPVCwgRElTIGVxdWl0aWVzDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShxdWFudG1vZCkNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojc3RhcnRpbmcgZGF0YQ0KZHQ8LScyMDE4LTItMScNCiNnZXR0aW5nIGRhdGENCmFhcGxfZGY8LWRhdGEuZnJhbWUoZ2V0U3ltYm9scy55YWhvbygnQUFQTCcsIGZyb209ZHQsIGF1dG8uYXNzaWduPUYpKQ0KbmZseF9kZjwtZGF0YS5mcmFtZShnZXRTeW1ib2xzLnlhaG9vKCdORkxYJywgZnJvbT1kdCwgYXV0by5hc3NpZ249RikpDQpyb2t1X2RmPC1kYXRhLmZyYW1lKGdldFN5bWJvbHMueWFob28oJ1JPS1UnLCBmcm9tPWR0LCBhdXRvLmFzc2lnbj1GKSkNCnNwb3RfZGY8LWRhdGEuZnJhbWUoZ2V0U3ltYm9scy55YWhvbygnU1BPVCcsIGZyb209ZHQsIGF1dG8uYXNzaWduPUYpKQ0KZGlzX2RmPC1kYXRhLmZyYW1lKGdldFN5bWJvbHMueWFob28oJ0RJUycsIGZyb209ZHQsIGF1dG8uYXNzaWduPUYpKQ0KYGBgDQojIyBEYXRhIE92ZXJ2aWV3DQpMb29raW5nIGF0IFNQT1QgZXF1aXR5IGRhdGEgYXMgYW4gZXhhbXBsZSANCmBgYHtyfQ0Kc3BvdF90YWJsZTwtaGVhZChzcG90X2RmLDEwKQ0Kc3BvdF90YWJsZQ0KYGBgDQojIyBEYXRhIFByZXBhcmF0aW9uDQpNYW5pcHVsYXRpbmcgcmF3IGVxdWl0eSBkYXRhIGZvciBmdXR1cmUgYW5hbHlzaXMNCmBgYHtyfQ0KDQpkYXRhX3ByZXBfZnVuYzwtZnVuY3Rpb24oeCwgeSl7DQogICNzbWENCiAgc21hMTA8LVNNQSh4WzZdLCBuPTEwKQ0KICAjZW1hDQogIGVtYTIwPC1FTUEoeFs2XSwgbj0yMCkNCiAgI0JCYW5kcw0KICBiYmFuZHMyMCA8LSBkYXRhLmZyYW1lKEJCYW5kcyggQ2woeCksIG49MjAsIHNkPTIpKQ0KICBiYmFuZHMyMCA8LSBiYmFuZHMyMFssYygxLDMpXQ0KICAjY2hhbmdpbmcgY29sbmFtZXMNCiAgY29sbmFtZXMoc21hMTApPC1jKHBhc3RlMCh5LCcuU01BJykpDQogIGNvbG5hbWVzKGVtYTIwKTwtYyhwYXN0ZTAoeSwnLkVNQScpKQ0KICBjb2xuYW1lcyhiYmFuZHMyMCk8LWMocGFzdGUwKHksJy5kbicpLCBwYXN0ZTAoeSwnLnVwJykpDQogICNtZXJnZS9mb3JtYXR0aW5nDQogIG5ld19kZjwteA0KICBuZXdfZGY8LWNiaW5kKG5ld19kZiwgc21hMTApDQogIG5ld19kZjwtY2JpbmQobmV3X2RmLCBlbWEyMCkNCiAgbmV3X2RmPC1jYmluZChuZXdfZGYsIGJiYW5kczIwKQ0KICBuZXdfZGY8LWNiaW5kKERhdGU9cm93bmFtZXMobmV3X2RmKSwgbmV3X2RmKQ0KICByb3duYW1lcyhuZXdfZGYpPC0xOm5yb3cobmV3X2RmKQ0KICAjdm9sdW1lIGRpZmZlcmVudGlhdGlvbiBjYWxjDQogIGZvcih2IGluIDE6bGVuZ3RoKG5ld19kZlssMV0pKXsNCiAgICBpZihuZXdfZGZbdiwgNV0gPj0gbmV3X2RmW3YsIDJdKXsNCiAgICAgIG5ld19kZlt2LCAndm9sdW1ldHlwZSddPSdJbmNyZWFzaW5nJw0KICAgIH0gZWxzZSBpZihhYnMobmV3X2RmW3YsIDVdLW5ld19kZlt2LDJdKSA8IDAuNCl7DQogICAgICBuZXdfZGZbdiwgJ3ZvbHVtZXR5cGUnXT0nRG9qaScNCiAgICB9IGVsc2Ugew0KICAgICAgbmV3X2RmW3YsICd2b2x1bWV0eXBlJ109J0RlY3JlYXNpbmcnDQogICAgfQ0KICB9DQogICNyZXR1cm4NCiAgcmV0dXJuKG5ld19kZikNCn0NCiNydW5uaW5nIGZ1bmMNCmFhcGxfZGY8LWRhdGFfcHJlcF9mdW5jKGFhcGxfZGYsICdBQVBMJykNCmRpc19kZjwtZGF0YV9wcmVwX2Z1bmMoZGlzX2RmLCAnRElTJykNCm5mbHhfZGY8LWRhdGFfcHJlcF9mdW5jKG5mbHhfZGYsICdORkxYJykNCnJva3VfZGY8LWRhdGFfcHJlcF9mdW5jKHJva3VfZGYsICdST0tVJykNCnNwb3RfZGY8LWRhdGFfcHJlcF9mdW5jKHNwb3RfZGYsICdTUE9UJykNCmBgYA0KIyMgRGF0YSBWaXN1YWxpemF0aW9uDQpDcmVhdGluZyBhIGR5bmFtaWMgcGxvdCB3aXRoIFBsb3RseSBsaWINCmBgYHtyfQ0KZGF0YV92aXoxX2Z1bmM8LWZ1bmN0aW9uKGRmLCBlcV9uYW1lKXsNCiAgI3N0YXJ0aW5nIGRhdGENCiAgZHQ8LScyMDE4LTItMScNCiAgI3RvZGF5J3MgZGF0ZQ0KICB0b2RheV9kYXRlPC1TeXMuRGF0ZSgpDQogICNwbG90DQogIGNhbmRsZV9maWcgPC0gcGxvdF9seSh4ID0gZGZbWzFdXSwgdHlwZT0iY2FuZGxlc3RpY2siLA0KICAgICAgICAgICAgICAgICAgICAgIG9wZW4gPSBkZltbMl1dLCBjbG9zZSA9IGRmW1s1XV0sDQogICAgICAgICAgICAgICAgICAgICAgaGlnaCA9IGRmW1szXV0sIGxvdyA9IGRmW1s0XV0sIG5hbWU9ZXFfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICB3aWR0aD05MDAsIGhlaWdodD04MDApDQogIGNhbmRsZV9maWcgPC0gY2FuZGxlX2ZpZyAlPiUgYWRkX2xpbmVzKHggPSBkZltbMV1dLCB5ID0gZGZbWzhdXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JnYigyNTUsIDE1MywgMTAyKScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuOCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSdTTUEtMTAnLCBpbmhlcml0ID0gRikNCiAgY2FuZGxlX2ZpZyA8LSBjYW5kbGVfZmlnICU+JSBhZGRfbGluZXMoeCA9IGRmW1sxXV0sIHkgPSBkZltbOV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3I9J2JsdWUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9MC44KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9J0VNQS0yMCcsIGluaGVyaXQgPSBGKQ0KICBjYW5kbGVfZmlnIDwtIGNhbmRsZV9maWcgJT4lIGFkZF9saW5lcyh4ID0gZGZbWzFdXSwgeSA9IGRmW1sxMF1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3I9JyNkYWQzZTAnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9MC44LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eT0wLjYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0nQkJhbmRzLmRuJywgaW5oZXJpdCA9IEYpDQogIGNhbmRsZV9maWcgPC0gY2FuZGxlX2ZpZyAlPiUgYWRkX2xpbmVzKHggPSBkZltbMV1dLCB5ID0gZGZbWzExXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvcj0nI2RhZDNlMCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aD0wLjgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGFjaXR5PTAuNiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSdCQkFuZHMudXAnLCBpbmhlcml0ID0gRikNCiAgdm9sdW1lX2ZpZyA8LSBhYXBsX2RmICU+JSBwbG90X2x5KHg9IGRmW1sxXV0sIHk9IGRmW1s2XV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0nYmFyJywgbmFtZSA9IGRmW1sxMl1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSBkZltbMTJdXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnM9YygnI2ZmOTk5OScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyNmZmZmOTknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcjOTlmZmIzJykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApDQogICNsYXlvdXQNCiAgdm9sdW1lX2ZpZyA8LSB2b2x1bWVfZmlnICU+JSBsYXlvdXQoeWF4aXM9bGlzdCh0aXRsZT0nVm9sdW1lJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGVmb250PWxpc3Qoc2l6ZT0xNSkpKQ0KICBmaW5hbF9maWcgPC0gc3VicGxvdChjYW5kbGVfZmlnLCB2b2x1bWVfZmlnLCBoZWlnaHRzID0gYygwLjcsMC4yKSwgbnJvd3M9MiwNCiAgICAgICAgICAgICAgIHNoYXJlWCA9IFRSVUUsIHRpdGxlWSA9IFRSVUUpDQogIGZpbmFsX2ZpZyA8LSBmaW5hbF9maWcgJT4lIGxheW91dCgNCiAgICB0aXRsZT1saXN0KHRleHQ9cGFzdGUwKGVxX25hbWUsJzogJyxkdCwnIC0gJyxhcy5jaGFyYWN0ZXIodG9kYXlfZGF0ZSkpLA0KICAgICAgICAgICAgICAgZm9udD1saXN0KHNpemU9MjIpLCB5ID0gMC45NyksDQogICAgeGF4aXM9bGlzdCh0eXBlPSdkYXRlJywgdGlja2Zvcm1hdCA9ICIlZCAlQiA8YnI+JVkiLA0KICAgICAgICAgICAgICAgdGl0bGU9RkFMU0UsIHRpY2tmb250PWxpc3Qoc2l6ZT0xNCkpLA0KICAgIHlheGlzPWxpc3QodGl0bGU9IlByaWNlIiwgdGl0bGVmb250PWxpc3Qoc2l6ZT0xNiksDQogICAgICAgICAgICAgICB0aWNrZm9udD1saXN0KHNpemU9MTQpKSwNCiAgICBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbiA9ICdoJywgeCA9IDAuNSwgeSA9IDAuOTMsDQogICAgICAgICAgICAgICAgeGFuY2hvciA9ICdjZW50ZXInLCBmb250ID0gbGlzdChzaXplPTEyKSwNCiAgICAgICAgICAgICAgICBiZ2NvbG9yID0gJ3RyYW5zcGFyZW50JykNCiAgDQogICkNCiAgI3Nob3cNCiAgZmluYWxfZmlnDQp9DQpgYGANCiMjIyBBcHBsZSAoQUFQTCkgR3JhcGgNCmBgYHtyfQ0KZGF0YV92aXoxX2Z1bmMoYWFwbF9kZiwgJ0FBUEwnKQ0KYGBgDQojIyMgRGlzbmV5IChESVMpIEdyYXBoDQpgYGB7cn0NCmRhdGFfdml6MV9mdW5jKGRpc19kZiwgJ0RJUycpDQpgYGANCiMjIyBOZXRmbGl4IChORkxYKSBHcmFwaA0KYGBge3J9DQpkYXRhX3ZpejFfZnVuYyhuZmx4X2RmLCAnTkZMWCcpDQpgYGANCiMjIyBSb2t1IChST0tVKSBHcmFwaA0KYGBge3J9DQpkYXRhX3ZpejFfZnVuYyhyb2t1X2RmLCAnUk9LVScpDQpgYGANCiMjIyBTcG90aWZ5IChTUE9UKSBHcmFwaA0KYGBge3J9DQpkYXRhX3ZpejFfZnVuYyhzcG90X2RmLCAnU1BPVCcpDQpgYGANCiMjIFBvcnRmb2xpbyBBbmFseXNpcw0KQW5hbHlzaXMgb2YgcmV0dXJucyBhbmQgZXF1YWxseSB3ZWlnaHRlZCBwb3J0Zm9saW8gY2FzZSBzdHVkeQ0KDQpQZXJmb3JtYW5jZSBvZiBzZWxlY3RlZCBlcXVpdGllcyBpbmRlcGVuZGVudGx5DQpgYGB7cn0NCiMnQUFQTCcsICdESVMnLCAnTkZMWCcsICdST0tVJywgJ1NQT1QnDQphYXBsX2RyZXQ8LW5hLm9taXQoZGFpbHlSZXR1cm4oQWQoZ2V0U3ltYm9scy55YWhvbygnQUFQTCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbT1kdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJpb2RpY2l0eT0nZGFpbHknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG8uYXNzaWduPUYpKSwgdHlwZT0nYXJpdGhtZXRpYycpKQ0KZGlzX2RyZXQ8LW5hLm9taXQoZGFpbHlSZXR1cm4oQWQoZ2V0U3ltYm9scy55YWhvbygnRElTJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tPWR0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmlvZGljaXR5PSdkYWlseScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0by5hc3NpZ249RikpLCB0eXBlPSdhcml0aG1ldGljJykpDQpuZmx4X2RyZXQ8LW5hLm9taXQoZGFpbHlSZXR1cm4oQWQoZ2V0U3ltYm9scy55YWhvbygnTkZMWCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbT1kdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJpb2RpY2l0eT0nZGFpbHknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG8uYXNzaWduPUYpKSwgdHlwZT0nYXJpdGhtZXRpYycpKQ0Kcm9rdV9kcmV0PC1uYS5vbWl0KGRhaWx5UmV0dXJuKEFkKGdldFN5bWJvbHMueWFob28oJ1JPS1UnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb209ZHQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyaW9kaWNpdHk9J2RhaWx5JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvLmFzc2lnbj1GKSksIHR5cGU9J2FyaXRobWV0aWMnKSkNCnNwb3RfZHJldDwtbmEub21pdChkYWlseVJldHVybihBZChnZXRTeW1ib2xzLnlhaG9vKCdTUE9UJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tPWR0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmlvZGljaXR5PSdkYWlseScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0by5hc3NpZ249RikpLCB0eXBlPSdhcml0aG1ldGljJykpDQojcmVuYW1pbmcgY29scw0KY29sbmFtZXMoYWFwbF9kcmV0KTwtJ0FBUEwuQWQuUmV0dXJucycNCmNvbG5hbWVzKGRpc19kcmV0KTwtJ0RJUy5BZC5SZXR1cm5zJw0KY29sbmFtZXMobmZseF9kcmV0KTwtJ05GTFguQWQuUmV0dXJucycNCmNvbG5hbWVzKHJva3VfZHJldCk8LSdST0tVLkFkLlJldHVybnMnDQpjb2xuYW1lcyhzcG90X2RyZXQpPC0nU1BPVC5BZC5SZXR1cm5zJw0KI21lcmdpbmcNCmRyZXRfZGF0YTwtY2JpbmQoYWFwbF9kcmV0LGRpc19kcmV0LA0KICAgICAgICAgICAgICAgICBuZmx4X2RyZXQscm9rdV9kcmV0LHNwb3RfZHJldCkNCg0KDQp0YWJsZS5Bbm51YWxpemVkUmV0dXJucyhkcmV0X2RhdGEsIHNjYWxlPTI1MiwgUmY9MC4wMTUvMjUyKQ0KYGBgDQpgYGB7ciBmaWcuaGVpZ2h0PTEwfQ0KI3Bsb3R0aW5nIHBlcmZvcm1hbmNlDQpjaGFydHMuUGVyZm9ybWFuY2VTdW1tYXJ5KGRyZXRfZGF0YSwgbWFpbj0nUG9ydGZvbGlvIFBlcmZvcm1hbmNlJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgUmY9MC4wMTUvMjUyLCBwbG90LmVuZ2luZT0nZGVmYXVsdCcpDQpgYGANCg0KRXF1YWxseSB3ZWlnaHRlZCBwb3J0Zm9saW8gY2FzZSBzdHVkeSBhbmQgYW5hbHlzaXMNCmBgYHtyfQ0KI2VxIHdlaWdodGVkIHBvcnRmb2xpbw0KcG9ydHJldF9kZjwtUmV0dXJuLnBvcnRmb2xpbyhkcmV0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodHM9YyguMjAsLjIwLC4yMCwuMjAsLjIwKSkNCmNvbG5hbWVzKHBvcnRyZXRfZGYpPC0nUG9yZm9saW8uRXF3LlJldHVybnMnDQoNCiNwZXJmb3JtYW5jZSBiZW5jaG1hcmsNCmJlbmNobWFya1ByaWNlczwtbmEub21pdChkYWlseVJldHVybihBZChnZXRTeW1ib2xzLnlhaG9vKCdeR1NQQycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbT1kdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJpb2RpY2l0eT0nZGFpbHknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG8uYXNzaWduPUYpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPSdhcml0aG1ldGljJykpDQpjb2xuYW1lcyhiZW5jaG1hcmtQcmljZXMpPC0nQmVuY2htYXJrLlNQNTAwLlJldHVybnMnDQoNCiNtZXJnaW5nIHBvcnRmb2xpbyBhbmQgYmVuY2htYXJrIHRvZ2V0aGVyDQpFcVdQb3J0LkJlbmNobWFya19kZjwtbWVyZ2UocG9ydHJldF9kZiwgYmVuY2htYXJrUHJpY2VzKQ0KI3BlcmZvcm1hbmNlIHRhYmxlIA0KdGFibGUuQW5udWFsaXplZFJldHVybnMoRXFXUG9ydC5CZW5jaG1hcmtfZGYsIHNjYWxlPTI1MiwgUmY9MC4wMTUvMjUyKQ0KYGBgDQpgYGB7cn0NCg0KRXFXUG9ydC5CZW5jaG1hcmtfZGY8LWRhdGEuZnJhbWUoRXFXUG9ydC5CZW5jaG1hcmtfZGYpDQpFcVdQb3J0LkJlbmNobWFya19kZjwtY2JpbmQoRGF0ZT1yb3duYW1lcyhFcVdQb3J0LkJlbmNobWFya19kZiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXFXUG9ydC5CZW5jaG1hcmtfZGYpDQpyb3duYW1lcyhFcVdQb3J0LkJlbmNobWFya19kZik8LTE6bnJvdyhFcVdQb3J0LkJlbmNobWFya19kZikNCg0KcGVyZl9maWc8LUVxV1BvcnQuQmVuY2htYXJrX2RmICU+JSBwbG90X2x5KHg9IH5EYXRlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PX5Qb3Jmb2xpby5FcXcuUmV0dXJucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0nc2NhdHRlcicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU9J2xpbmVzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3I9J2dyZWVuJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTAuOCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSdQb3J0Zm9saW8nLCBpbmhlcml0ID0gRiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwMCwgaGVpZ2h0PTYwMCkNCnBlcmZfZmlnPC1wZXJmX2ZpZyAlPiUgYWRkX2xpbmVzKHggPSB+RGF0ZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB+QmVuY2htYXJrLlNQNTAwLlJldHVybnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvcj0nYmx1ZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aD0wLjgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0nUyZQNTAwJywgaW5oZXJpdCA9IEYpDQoNCiNzdGFydGluZyBkYXRhDQpkdDwtJzIwMTgtMi0xJw0KI3RvZGF5J3MgZGF0ZQ0KdG9kYXlfZGF0ZTwtU3lzLkRhdGUoKQ0KDQojbGF5b3V0DQpwZXJmX2ZpZzwtIHBlcmZfZmlnICU+JSBsYXlvdXQoDQogIHRpdGxlPWxpc3QodGV4dD1wYXN0ZTAoJ1BvcnRmb2xpbyAtIFMmUDUwMCcsJzogJyxkdCwnIC0gJyxhcy5jaGFyYWN0ZXIodG9kYXlfZGF0ZSkpLA0KICAgICAgICAgICAgICAgZm9udD1saXN0KHNpemU9MjIpLCB5ID0gMC45NyksDQogIHhheGlzPWxpc3QodHlwZT0nZGF0ZScsIHRpY2tmb3JtYXQgPSAiJWQgJUIgPGJyPiVZIiwNCiAgICAgICAgICAgICAgIHRpdGxlPUZBTFNFLCB0aWNrZm9udD1saXN0KHNpemU9MTQpKSwNCiAgeWF4aXM9bGlzdCh0aXRsZT0iUmV0dXJucyIsIHRpdGxlZm9udD1saXN0KHNpemU9MTYpLA0KICAgICAgICAgICAgICAgdGlja2ZvbnQ9bGlzdChzaXplPTE0KSkNCiAgDQopDQoNCnBlcmZfZmlnDQoNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==